package com.andooco.dataq.service.query;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.andooco.dataq.service.func.FuncService;
import com.andooco.dataq.service.func.dto.FuncDto;
import com.andooco.dataq.service.jdbc.JdbcService;
import com.andooco.dataq.service.jdbc.dto.JdbcDto;
import com.andooco.dataq.util.DoConnection;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

/**
 * 数据查询操作管理
 *
 * @author andooco
 * 20201127
 */
@Slf4j
@Service("QueryService")
public class QueryService {
    @Autowired
    private FuncService funcService;
    @Autowired
    private JdbcService jdbcService;

    /**
     * 初始化下拉框信息
     *
     * @param
     * @return
     */
    public Map<String, Object> initData() throws UnsupportedEncodingException {
        log.info("进入QueryService 初始化下拉框入口");
        List<JdbcDto> jdbcDtos = jdbcService.getJdbcDtosCached();
        List<FuncDto> funcDtos = funcService.getFuncDtosCached();
        Map<String, Object> result = new HashMap<>();
        result.put("jdbcDtos", jdbcDtos);
        result.put("funcDtos", funcDtos);
        log.info("初始化下拉框结果：{}", JSON.toJSONString(result));
        return result;
    }

    /**
     * 查询sql
     *
     * @param
     * @return
     */
    public String queryThisSql(String funcUid) throws UnsupportedEncodingException {
        log.info("进入QueryService 查询sql入口");
        List<FuncDto> funcDtos = funcService.getFuncDtosCached();
        //定义filters
        Predicate<FuncDto> strFilter = (funcDto) -> (funcDto.getFuncUid().equals(funcUid));
        List<FuncDto> funcDtoList = new ArrayList<>();
        funcDtos.stream()
                .filter(strFilter)
                .forEach((strlist) -> funcDtoList.add(strlist));
        log.info("初始化下拉框结果：{}", JSON.toJSONString(funcDtoList));
        return funcDtoList.get(0).getFuncContent();
    }

    /**
     * 查询结果
     *
     * @param
     * @return
     */
    public JSONObject queryResult(String uid, String funcId, String selectParams) throws UnsupportedEncodingException, SQLException {
        log.info("进入QueryService 查询结果入口");
        List<JdbcDto> jdbcDtos = jdbcService.getJdbcDtosCached();
        //定义filters
        Predicate<JdbcDto> strFilter = (jdbcDto) -> (jdbcDto.getUid().equals(uid));
        List<JdbcDto> jdbcDtoList = new ArrayList<>();
        jdbcDtos.stream()
                .filter(strFilter)
                .forEach((strlist) -> jdbcDtoList.add(strlist));
        //按理只有一条
        JdbcDto jdbcDto = jdbcDtoList.get(0);
        log.info("准备执行的数据库为：{}", JSON.toJSONString(jdbcDto));
        Connection connection = DoConnection.connection(jdbcDto.getJdbcType(), "单节点", "", jdbcDto.getJdbcUrl(), jdbcDto.getJdbcPort(), jdbcDto.getJdbcSID(), jdbcDto.getJdbcUser(), jdbcDto.getJdbcPassword());
        //组装sql
        List<FuncDto> funcDtos = funcService.getFuncDtosCached();
        //定义filters
        Predicate<FuncDto> strFilterFunc = (funcDto) -> (funcDto.getFuncUid().equals(funcId));
        List<FuncDto> funcDtoListFunc = new ArrayList<>();
        funcDtos.stream()
                .filter(strFilterFunc)
                .forEach((funcDtoList) -> funcDtoListFunc.add(funcDtoList));

        String beginData = funcDtoListFunc.get(0).getFuncContent();
        String sql = initSelectHtml(beginData, selectParams);
        PreparedStatement ps = connection.prepareStatement(sql);
//        ps.setint(1,id);
//        ps.setstring(2,name);
        sql = sql.toLowerCase();
        JSONObject jsonObject = new JSONObject();
        if (sql.trim().startsWith("select")) {
            ResultSet rs = ps.executeQuery(sql);
            List<Map<String, String>> result = convertList(rs);
            log.info("查询数据库返回的结果：{}" + JSON.toJSONString(result));
            jsonObject.put("queryData", result);
        } else {
            int resultNum = ps.executeUpdate(sql);
            connection.commit();
            log.info("非查询操作执行完毕：{}", resultNum);
            jsonObject.put("resultNum", resultNum);
        }
        connection.close();
        return jsonObject;
    }

    public String initSelectHtml(String beginData, String selectParams) {
        int paramNum = beginData.split("#").length - 1;
        int m = 1;
        selectParams = selectParams.substring(0, selectParams.lastIndexOf("#"));
        for (int i = 1; i <= paramNum / 2; i++) {
            int begin = m;
            int end = m + 1;
            String beginPos = "#" + begin + "@";
            String endPos = "#" + end + "@";
            String temp = beginData.substring(beginData.indexOf(beginPos), beginData.indexOf(endPos) + endPos.length());
            String[] params = selectParams.split(beginPos);
            beginData = beginData.replace(temp, params[0]);
            if (params.length > 1) {
                selectParams = params[1];
            }
            m = m + 2;
        }
        return beginData;
    }

    /**
     * 数据库查询结果转换为list
     *
     * @param rs
     * @return
     * @throws SQLException
     */
    private static List<Map<String, String>> convertList(ResultSet rs) throws SQLException {
        List list = new ArrayList();
        ResultSetMetaData md = rs.getMetaData();
        int columnCount = md.getColumnCount();
        while (rs.next()) {
            Map<String, String> rowData = new HashMap<>();
            for (int i = 1; i <= columnCount; i++) {
                //先全部转为String对象
                try {
                    rowData.put(md.getColumnName(i), String.valueOf(rs.getObject(i)));
                } catch (Exception e) {
                    rowData.put(md.getColumnName(i), rs.getDate(i) + " " + rs.getTime(i));
                    log.error("执行sql报错", e);
                }
            }
            list.add(rowData);
        }
        return list;

    }
}
